#pragma once
#include <vector>
#include "Delegate.hpp"

using namespace std;

namespace Typhoon {
	template<class T> class Event
	{
	public:
		Event();
		~Event();

		void operator += (IDelegate<T>* handler);
		void operator -= (IDelegate<T>* handler);

		void operator () (T value);

		void Clear();

		int Count();

	private:
		vector<IDelegate<T>*> handlers;
	};
}

template<class T> Typhoon::Event<T>::Event() {
}

template<class T> Typhoon::Event<T>::~Event() {
	Clear();
}

template<class T> void Typhoon::Event<T>::operator+=(IDelegate<T>* handler) {
	handlers.push_back(handler);
}

template<class T> void Typhoon::Event<T>::operator-=(IDelegate<T>* handler) {
	const int size = handlers.size();
	for (int i = 0; i<size; i++) {
		if (handler->Match(handlers[i])) {
			//handlers.erase(handlers::find(handler.begin(), handlers.end(), handlers[i]));
			delete handlers[i];
			handlers.erase(handlers.begin() + i);
			break;
		}
	}
	delete handler;
}

template<class T> void Typhoon::Event<T>::operator() (T value) {
	//vector<IDelegate<T>*> temp = handlers;
	//const int size = temp.size();
	//for (int i = 0; i<size; i++) {
	//	temp[i]->Invoke(value);
	//}

	//const int size = handlers.size();
	for (unsigned int i = 0; i<handlers.size(); i++) {
		handlers[i]->Invoke(value);
	}
}

template<class T> void Typhoon::Event<T>::Clear() {
	const int size = handlers.size();
	for (int i = 0; i<size; i++) {
		delete handlers[i];
	}
	handlers.clear();
}

template<class T> int Typhoon::Event<T>::Count() {
	return handlers.size();
}

template<class Object, class Value> Typhoon::IDelegate<Value>* event_handler(Object* object, void (Object::* Method)(Value value)) {
	return new Typhoon::Delegate<Object, Value>(object, Method);
}